package gpl.pierrick.brihaye.aramorph;

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

/**
 * A dictionary that reads from database.
 * @author Ahmed Saad, 2006
 */
public class JDBCDictionary implements Dictionary {
	/**A logger to write log messages*/
	private static Logger logger = Logger.getLogger(JDBCDictionary.class.getName());

	/**Dictionary name*/
	protected String dictName;
	
	/**A read-only connection to database*/
	protected DBManager readonlyManager;
	
	/**Whether this dictionary is normalized or not*/
	protected boolean dictionaryNormalized;

	/**
	 * Tells whether this dictionary is normalized or not. A normalized dictionary
	 * checks entries after normalizing.
	 * @return true if this dictionary is normalized
	 */
	public boolean isDictionaryNormalized() {
		return dictionaryNormalized;
	}

	/**
	 * Sets the dictionary to be normalized
	 * @param dictionaryNormalized whether the dictionary to be normalized or not.
	 */
	public void setDictionaryNormalized(boolean dictionaryNormalized) {
		this.dictionaryNormalized = dictionaryNormalized;
	}

	/**
	 * Constructs a new dictionary which points to a table in database with the given name
	 * @param dictName name for this dictionary. There must be a corresponding table in
	 * database with the given name
	 */
	public JDBCDictionary(String dictName, boolean dictionaryNormalized) {
		this.dictName = dictName;
		this.dictionaryNormalized = dictionaryNormalized;
		this.readonlyManager = DBManager.readonlyConnection;
	}

	public boolean contains(String entry) {
		return readonlyManager.containsEntry(dictName,entry,dictionaryNormalized);
	}

	public Iterator<DictionaryEntry> getIterator(String entry) {
		return readonlyManager.getDictionaryEntries(dictName,entry,dictionaryNormalized).iterator();
	}

	public Iterator<DictionaryEntry> getIteratorForGloss(String gloss) {
		return readonlyManager.getDictionaryEntriesByGloss(gloss).iterator();
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		readonlyManager = null;
	}

	/**
	 * Creates the database (fills in tables) from the XML dictionaries.
	 * @param xmlFile an input stream to the XML file to be loaded.
	 */
	public void createFromXML(InputStream is) {
		SAXParserFactory factory = SAXParserFactory.newInstance();
		factory.setValidating(false);
		try {
			SAXParser sax = factory.newSAXParser();
			XMLDictionaryReader dl = new XMLDictionaryReader(dictName);
			sax.parse(is,dl);
//			dl.writeStats();
		} catch (ParserConfigurationException pce) {
			logger.warning("Could not create that parser.");
			logger.warning(pce.getMessage());
		} catch (SAXException se) {
			logger.warning("Problem with the SAX parser");
			logger.warning(se.getMessage());
		} catch (IOException ioe) {
			logger.warning("Error reading file.");
			logger.warning(ioe.getMessage());
		}
	}
	
}

class XMLDictionaryReader extends XMLDictionaryLoader {

	/**Name of the dictionary to be loaded in database*/
	private final String dictName;
	
	/**A connection to database that can update*/
	private DBManager dbUpdateConnection = DBManager.getUpdateConnection();

	public XMLDictionaryReader (String dictName) {
		super(null);
		this.dictName = dictName;
	}

	@Override
	public void startDocument() throws SAXException {
		dbUpdateConnection.clearTable(dictName);
	}

	@Override
	protected void entryLoaded(DictionaryEntry de) {
		dbUpdateConnection.addDictionaryEntry(dictName,de);
	}
	
	
}